/**
 * 
 */
package ictius.estructuras.implement;

import ictius.demonio.Informante;

/**
 * @author tadeo
 *
 */
public class Listado {
	private Nodulo head;
	private int listCount;
	
	/**
	 *  LinkedList constructor
	 */
	public Listado()
	{
		Informante.asustar("Se acaba de crear una nueva Lista.");
		// this is an empty list, so the reference to the head node
		// is set to a new node with no data
		head = new Nodulo(null);
		listCount = 0;
	}
	
	/**
	 * Inserta un elemento nuevo al final de la Lista.
	 * @param data
	 */
	public void add(Object data){
		Nodulo temp = new Nodulo(data);
		Informante.asustar("Se va a agregar un dato en la Lista: " + data);
		Nodulo current = head;
		// starting at the head node, crawl to the end of the list
		while(current.getNext() != null)
		{
			current = current.getNext();
		}
		// the last node's "next" reference set to our new node
		current.setNext(temp);
		listCount++;// increment the number of elements variable
	}
	
	/**
	 * Inserta un elemento nuevo en la posición indicada con <code>index</code>.
	 * @param data
	 * @param index
	 */
	public void add(Object data, int index)
	// post: inserts the specified element at the specified position in this list.
	{
		Nodulo temp = new Nodulo(data);
		Nodulo current = head;
		// crawl to the requested index or the last element in the list,
		// whichever comes first
		for(int i = 1; i < index && current.getNext() != null; i++)
		{
			current = current.getNext();
		}
		// set the new node's next-node reference to this node's next-node reference
		temp.setNext(current.getNext());
		// now set this node's next-node reference to the new node
		current.setNext(temp);
		listCount++;// increment the number of elements variable
	}
	
	/**
	 * Obtiene un elemento de la lista a partirde una dirección <code>index</code>.
	 * @param index
	 * @return Object de la lista.
	 * @return null si no lo encuentra.
	 */
	public Object get(int index)
	// post: returns the element at the specified position in this list.
	{
		// index must be 1 or higher
		if(index <= 0)
			return null;
		
		Nodulo current = head.getNext();
		for(int i = 1; i < index; i++)
		{
			if(current.getNext() == null)
				return null;
			
			current = current.getNext();
		}
		return current.getData();
	}
	
	/**
	 * Quita de la lista un objeto determinado según <code>index</code>
	 * @param index
	 * @return verdadero si ha sido eliminado.
	 * @return falso en caso de que no exista.
	 */
	public boolean remove(int index)
	// post: removes the element at the specified position in this list.
	{
		// if the index is out of range, exit
		if(index < 1 || index > size())
			return false;
		
		Nodulo current = head;
		for(int i = 1; i < index; i++)
		{
			if(current.getNext() == null)
				return false;
			
			current = current.getNext();
		}
		current.setNext(current.getNext().getNext());
		listCount--; // decrement the number of elements variable
		return true;
	}
	
	/**
	 *  post: returns the number of elements in this list.
	 * @return el tamaño de la lista.
	 */
	public int size(){
		return listCount;
	}
	
	/**
	 * Recorre la lista mostrando su contenido en forma de método recursivo.
	 */
	public String toString()
	{
		Nodulo current = head.getNext();
		String output = "";
		while(current != null)
		{
			output += "[" + current.getData().toString() + "]";
			current = current.getNext();
		}
		return output;
	}
	
	/**
	 * Método para listar el contenido de la Lista en forma recursiva. 
	 * Para poder utilizarso es necesario cargarlo con el tamaño de la Lista, es decir, 
	 * con el método <code>size()</code>.
	 * @param tam es el valor de la Lista completa.
	 */
	public void listar(int tam){
		if (tam == 0){
			System.out.println("La lista está vacía o ha sido recorrida por completo.");
		// return null;
		}else {
			System.out.println(this.get(tam).toString());
                            System.out.println("Son libros");
			this.listar(--tam);
			//return this.get(tam);
		}
	}
}